package com.linkhub.oms.admin.modules.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import com.google.common.collect.Lists;
import com.linkhub.oms.admin.modules.logistic.freighttemplate.domain.dto.LogisticFreightCalculateDTO;
import com.linkhub.oms.admin.modules.order.service.OrderInfoAssembleService;
import com.linkhub.oms.admin.modules.product.excel.enums.WrapUnitCellMappingEnum;
import com.linkhub.oms.admin.modules.product.service.LocalProductCalculateService;
import com.linkhub.oms.common.constant.SymbolConstant;
import com.linkhub.oms.common.util.QtBigDecimalUtil;
import com.linkhub.oms.common.util.QtOptionalUtil;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.dao.mpservice.ILocalProductService;
import com.linkhub.oms.entity.LocalProductEntity;
import com.linkhub.oms.entity.OrderAddressEntity;
import com.linkhub.oms.entity.resulttype.order.OrderInfoDO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.xmlbeans.impl.xb.xsdschema.Public;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;

/**
 * @Description: LocalProductCalculateService
 * @Author: echo
 * @Date: 2024/5/25 20:06
 * @Version: 1.0
 */
@Slf4j
@Service
public class LocalProductCalculateServiceImpl implements LocalProductCalculateService {

    public static final BigDecimal OUNCE_G = NumberUtil.toBigDecimal("28.3495");
    public static final BigDecimal FOOT_CM = NumberUtil.toBigDecimal("30.48");
    public static final BigDecimal BASE = NumberUtil.toBigDecimal("50");
    @Resource
    private OrderInfoAssembleService orderInfoAssembleService;
    @Resource
    private ILocalProductService localProductService;


    @Override
    public BigDecimal getOrderProductWeightTotal(String sysOrderId) {
        return this.getOrderProductWeightTotal(sysOrderId, true);
    }

    @Override
    public BigDecimal getOrderProductWeightTotal(String sysOrderId, boolean hydration) {
        BigDecimal baseWeight = hydration ? BASE : BigDecimal.ZERO;

        OrderInfoDO orderInfoDO = orderInfoAssembleService.assembleOrder(sysOrderId);
        Map<String,Integer> localSkuQuantityMap = orderInfoDO.getOrderProductQuantityMap();
        if (CollUtil.isEmpty(localSkuQuantityMap)) {
            return baseWeight;
        }
        List<LocalProductEntity> products = localProductService.listBySkuIds(localSkuQuantityMap.keySet());
        BigDecimal sum  = QtStreamUtil.sum(products, p->NumberUtil.mul(this.calculateProductWeightWithG(p), localSkuQuantityMap.getOrDefault(p.getSkuId(),0)));
        return NumberUtil.add(baseWeight, QtBigDecimalUtil.scale4(sum));
    }

    private BigDecimal calculateProductWeightWithG(LocalProductEntity product) {
        String[] properties = convertSpecificationProductInfo(product);
        if (CollUtil.size(properties) < 4) {
            return BigDecimal.ZERO;
        }

        BigDecimal weight = Convert.toBigDecimal(properties[3], BigDecimal.ZERO);
        Integer unit = product.getSpecificationUnit();
        if (WrapUnitCellMappingEnum.BS.getConvertValue().equals(unit)) {
            weight = NumberUtil.mul(weight, OUNCE_G);
        }

        return QtBigDecimalUtil.scale4(weight);
    }


    public BigDecimal getOrderProductVolumeTotal(String sysOrderId) {
        OrderInfoDO orderInfoDO = orderInfoAssembleService.assembleOrder(sysOrderId);
        Map<String,Integer> localSkuQuantityMap = orderInfoDO.getOrderProductQuantityMap();
        if (CollUtil.isEmpty(localSkuQuantityMap)) {
            return BigDecimal.ZERO;
        }

        List<LocalProductEntity> products = localProductService.listBySkuIds(localSkuQuantityMap.keySet());
        BigDecimal sum  = QtStreamUtil.sum(products, p->NumberUtil.mul(this.calculateProductVolumeWithCm(p), localSkuQuantityMap.getOrDefault(p.getSkuId(),0)));
        return QtBigDecimalUtil.scale4(sum);
    }

    private BigDecimal calculateProductVolumeWithCm(LocalProductEntity product) {
        String[] properties = convertSpecificationProductInfo(product);
        if (CollUtil.size(properties) < 3) {
            return BigDecimal.ZERO;
        }

        BigDecimal length = Convert.toBigDecimal(properties[0], BigDecimal.ZERO);
        BigDecimal width = Convert.toBigDecimal(properties[1], BigDecimal.ZERO);
        BigDecimal height = Convert.toBigDecimal(properties[2], BigDecimal.ZERO);
        BigDecimal volume = NumberUtil.mul(length, width, height);
        if (WrapUnitCellMappingEnum.BS.getConvertValue().equals(product.getSpecificationUnit())) {
            volume = NumberUtil.mul(volume, FOOT_CM);
        }

        return QtBigDecimalUtil.scale4(volume);
    }

    private String[] convertSpecificationProductInfo(LocalProductEntity product) {
        // 先取仓库复核的商品长宽高重，如果没有则取商家填的长宽高重
        String specificationProductInfo = StringUtils.defaultIfBlank(
                product.getSpecificationProductInfoRecheck(),
                product.getSpecificationProductInfo()
        );
        return StringUtils.split(specificationProductInfo, SymbolConstant.MID_LINE);
    }

    public LogisticFreightCalculateDTO calculateOrderWeightAndVolume(String sysOrderId) {
        LogisticFreightCalculateDTO logisticFreightCalculateDTO = new LogisticFreightCalculateDTO();
        logisticFreightCalculateDTO.setDynamicWeight(BASE);

        OrderInfoDO orderInfoDO = orderInfoAssembleService.assembleOrder(sysOrderId);
        Map<String,Integer> localSkuQuantityMap = orderInfoDO.getOrderProductQuantityMap();
        if (CollUtil.isEmpty(localSkuQuantityMap)) {
            logisticFreightCalculateDTO.setPackageWeight(BigDecimal.ZERO);
            logisticFreightCalculateDTO.setVolumeWeight(BigDecimal.ZERO);
            return logisticFreightCalculateDTO;
        }

        List<LocalProductEntity> products = localProductService.listBySkuIds(localSkuQuantityMap.keySet());
        BigDecimal orderWeight  = QtStreamUtil.sum(products, p->NumberUtil.mul(this.calculateProductWeightWithG(p), localSkuQuantityMap.getOrDefault(p.getSkuId(),0)));
        BigDecimal orderVolume  = QtStreamUtil.sum(products, p->NumberUtil.mul(this.calculateProductVolumeWithCm(p), localSkuQuantityMap.getOrDefault(p.getSkuId(),0)));

        logisticFreightCalculateDTO.setPackageWeight(orderWeight);
        logisticFreightCalculateDTO.setVolumeWeight(orderVolume);

        return logisticFreightCalculateDTO;
    }
}
